import prisma from "@/db/prisma";
import { BcryptService } from "../vendor/bcrypt";
import {
  AuthProfileResponse,
  CreateUserResponse,
  GetUserByIdResponse,
  UpdateUserResponse,
} from "@/types/api";
import { Prisma } from "@prisma/generated-client";

export class UserService {
  constructor(private bcryptService: BcryptService) {}

  async getRoles(userId: number) {
    const urs = await prisma.userOnRole.findMany({
      select: { role: true },
      where: { userId, deletedAt: null },
    });

    return urs.map((ur) => ur.role);
  }

  async getPermissions(userId: number, roleIds: number[]) {
    const rps = await prisma.roleOnPermission.findMany({
      select: { permission: true },
      where: { roleId: { in: roleIds }, deletedAt: null },
    });
    return rps.map((rp) => rp.permission);
  }

  async profile(userId: number): Promise<AuthProfileResponse> {
    const user = await prisma.user.findFirst({
      where: { id: userId },
      include: {
        avatar: true,
      },
    });

    const roles = await this.getRoles(userId);
    const permissions = await this.getPermissions(
      userId,
      roles.map((role) => role.id)
    );

    const { password, avatarId, ...userRest } = user;
    return {
      ...userRest,
      roles,
      permissions,
    };
  }

  async create(data: Prisma.UserCreateInput): Promise<CreateUserResponse> {
    return prisma.user.create({
      data,
    });
  }

  async findOne(userId: number): Promise<GetUserByIdResponse> {
    return prisma.user.findUnique({
      where: { id: userId, deletedAt: null },
    });
  }

  async update(
    userId: number,
    data: Prisma.UserUpdateInput
  ): Promise<UpdateUserResponse> {
    return prisma.user.update({
      where: { id: userId },
      data,
    });
  }

  async delete(userId: number) {
    await prisma.user.update({
      where: { id: userId },
      data: { deletedAt: new Date() },
    });
    return true;
  }

  async page(
    pageNum: number,
    pageSize: number,
    keywords?: string,
    orderBy?: Prisma.UserCountOrderByAggregateInput
  ) {
    const where: Prisma.UserWhereInput = {
      deletedAt: null,
      OR: keywords
        ? [
            { username: { contains: keywords } },
            { phone: { contains: keywords } },
            { email: { contains: keywords } },
          ]
        : undefined,
    };

    if (!orderBy) {
      orderBy = {
        createdAt: "desc",
      };
    }

    return prisma.$transaction(async (prisma) => {
      const total = await prisma.user.count({ where });
      const data = await prisma.user.findMany({
        skip: (pageNum - 1) * pageSize, // 跳过 (页码 - 1) * 每页数量 的记录
        take: pageSize, // 获取 pageSize 数量的记录
        where,
        orderBy,
      });

      return { data, total };
    });
  }
}
